<script setup>
import { onMounted, onUnmounted, ref } from 'vue';
import { Base } from '../threejs/base';
import * as THREE from 'three';
import fish from '../assets/fish.svg';
import snake from '../assets/snake.png';
import { gsap } from "gsap";
class Demo extends Base {
  mesh;
  m;
  time;
  controls = { color: 0xff0000 };
  geometry = { Geometry: 1 };
  initGui() {
    const g = this.gui.addFolder('调整这里试试');
    let colorChange = g.addColor(this.controls, 'color').name('色值');
    colorChange.onChange((value) => {
      console.log(value);
      for (let i = 0; i < this.scene.children.length; i++) {
        // 方式1
        // this.scene.children[i].material.uniforms.uColor.value.set(value); // 改变颜色为绿色
        // 方式2
        var newColor = new THREE.Color(this.controls.color);
        // 更新材质的颜色
        console.log(newColor);
        this.scene.children[i].material.uniforms.uColor.value.copy(newColor); // 如果颜色是uniform
      }
    });
    g.open();
  }

  initShader() {
    this.camera.position.set(0, 0, 4);
    this.camera.lookAt(new THREE.Vector3());
    this.renderer.setClearColor(0x160016, 1);

    this.loadImages([fish], (images) => {
      console.log(images);
      let coords = this.getImageCoords(images[0]);
      this.ini01(coords);
    });
  }
  getImageCoords(img) {
    const size = 100;
    const canvas = document.createElement('canvas');
    canvas.width = size;
    canvas.height = size;
    const ctx = canvas.getContext('2d');
    ctx.clearRect(0, 0, size, size);
    ctx.drawImage(img, 0, 0, size, size);
    const data = ctx.getImageData(0, 0, size, size).data;
    const imageCoords = [];
    // 过滤黑色
    for (let y = 0; y < size; y++) {
      for (let x = 0; x < size; x++) {
        const red = data[(y * size + x) * 4];
        // const green = data[(y * size + x) * 4 + 1];
        // const blue = data[(y * size + x) * 4 + 2];
        // const alpha = data[(y * size + x) * 4 + 3];
        if (red > 0 && red < 50) {
          imageCoords.push([x / size - 0.5, 0.5 - y / size]);
        }
      }
    }
    // document.body.appendChild(canvas);
    // canvas.classList.add('test-canvas');
    // canvas.style.position = 'fixed';
    // canvas.style.top = 0;
    // canvas.style.left = 0;

    return imageCoords;
  }
  loadImages(paths, whenLoaded) {
    const images = [];
    paths.forEach((path) => {
      const img = new Image();
      img.onload = function () {
        images.push(img);
        if (images.length === paths.length) {
          whenLoaded(images);
        }
      };
      img.src = path;
    });
  }
  getRandomValue(data) {
    return data[Math.floor(Math.random() * data.length)];
  }
  ini01(imageCoords) {
    const count = 10000;

    const geometry = new THREE.PlaneGeometry(1, 1, 30, 30);


    const vertexShader = /* GLSL */ `
      uniform float uTime;
      varying vec2 vUv;
      const float PI = 3.1415926;
      void main() {
        vUv = uv;
        // 1111
        // vec4 modelPosition = modelMatrix * vec4(position, 1.0);
        // modelPosition.y += 0.08 * sin(modelPosition.x * PI * 2.0 + uTime);
        // modelPosition.y += 0.1 * sin(modelPosition.z * PI * 1.5 + uTime);
        // gl_Position = projectionMatrix * viewMatrix * modelPosition;
        // 2222
        // vec3 newPos = position;
        // newPos.y += 0.06 * sin(newPos.x * PI * 2.0 + uTime);
        // newPos.x += 0.1 * sin(newPos.x  * PI * 1.5 + uTime);
        // gl_Position = projectionMatrix * modelViewMatrix * vec4(newPos, 1.0);
        // 3333
        vec4 modelPosition = modelMatrix * vec4(position, 1.0);
        modelPosition.y += 0.08 * sin(modelPosition.x * PI * 2.0 + uTime);
        modelPosition.y += 0.1 * sin(modelPosition.z * PI * 1.5 + uTime);
        gl_Position = projectionMatrix * viewMatrix * modelPosition;

      }
    `;
    const fragmentShader = /* GLSL */ `
      varying vec2 vUv;
      uniform sampler2D uTexture;
      void main() {
        vec4 color = texture2D(uTexture, vUv);
        gl_FragColor = vec4(color);
      }
    `;
    let material = new THREE.ShaderMaterial({
      uniforms: {
        uTime: { value: 0 },
        uColor: { value: new THREE.Color(0xff0000) },
        uTexture: {
          // value: new THREE.TextureLoader().load('../assets/snake.png'),
          value: new THREE.TextureLoader().load(snake),
        },
      },
      vertexShader,
      fragmentShader,
      // transparent: true,
      // depthTest: false,
      // depthWrite: false,
      // wireframe: true,

    });
    const mesh = new THREE.Mesh(geometry, material);
    this.scene.add(mesh);
  }

  renderContent() {
    // this.time += 0.05;
    let time = this.clock.getElapsedTime();
    for (let i = 0; i < this.scene.children.length; i++) {
      this.scene.children[i].material.uniforms.uTime.value = time;
      this.scene.children[i].rotation.y = time / 100;
    }
  }
}

let ins;
const dom = ref();
let run=()=>{
  console.log(ins.scene.children[0].material.uniforms.vProgress)
  gsap.to(ins.scene.children[0].material.uniforms.vProgress, {
    value: 1,
    onComplete: () => {
      // animating = false;
      // geometry.attributes.position.array = geometryAttributes[current];
      // geometry.attributes.position.needsUpdate = true;
      // material.uniforms.uColor.value = color;
      // material.uniforms.uProgress.value = 0;
      // ins.scene.children[0].material.uniforms.vProgress.value=0
    },
  });
}
onMounted(() => {
  ins = new Demo().init(dom.value);
});
onUnmounted(() => {
  ins.dispose();
});

const text = `
本示例主要学习了通过 uniforms 向着色器传递数据。示例主要代码如下：
\`\`\`
const m = new THREE.ShaderMaterial({
  uniforms: {
    uColor: { value: new THREE.Color(0xff0000) }
  },
  vertexShader: \`
    void main() {
      
      // position 是顶点的local坐标(Model坐标)
      // Model坐标 * ModelMatrix = World坐标；World坐标 * ViewMatrix = Camera坐标；Camera坐标 * ProjectionMatrix = 投影坐标

      gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
    }\`,
  fragmentShader: \`
    uniform vec3 uColor;  // 接收 uniforms 传过来的数据
    
    void main() {
      gl_FragColor = vec4(uColor, 1.0);
    }\`
});
\`\`\`
`;
</script>

<template>
  <div class="shader-box" ref="dom" @click="run"></div>
  <v-md-preview :text="text"></v-md-preview>
</template>

<style scoped></style>
